home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue29 / gmslabel / GMSLABEL.ZIP / GMSLABEL.PAS next >
Encoding:
Pascal/Delphi Source File  |  1997-11-13  |  13.7 KB  |  405 lines

  1. { GMSStickyLabel v1.4 Nov/12/97  by Glenn Shukster & Jacques Scoatarin
  2.  
  3.   GMS COMPUTING INC.                 Phone         (905)771-6458
  4.   53 COLVIN CRES.                    Fax                   -6819
  5.   THORNHILL, ONT.                    Compuserve:       72734,123
  6.   CANADA  L4J 2N7                    InternetId:Gms@Shaw.wave.ca
  7.                                      http://members.tor.shaw.wave.ca/~gms/
  8.  
  9.   Jacques Scoatarin                  Phone         (357)2-492591
  10.   52 Athalassis Ave. (flat 202)
  11.   Nicosia
  12.   Cyprus                             InternetId:j.scoatarin@cytanet.com.cy
  13.  
  14.  
  15. Purpose:
  16.   TLabel that will attach to any TWinControl Component on the
  17.   form like TEdit, TDBMemo, TButton etc.  There are other
  18.   components out there that make a label part of the edit or
  19.   memo etc. but they tie you too much to that other component.
  20.  
  21. Features:
  22.   1) All abilities of TLabel still exist
  23.   2) Works with Delphi 1,2,3.
  24.   3) _AlignTo: The position it will align to the TWinControl (left, right, top, bottom)
  25.   4) _AttachTo: The TWincontrol this label will attach to.
  26.   5) _Gap:     The space between the two components
  27.   6) Right Click: Component editor option
  28.            realigns all TGMSStickyLabels on the form(owner) to their _AttachTo components
  29.   7) Drop Label on any TWinControl and it asks to fill in _AttachTo with that component
  30.   8) Move TWinControl: the label will follow the _AttachTo component
  31.  
  32. Files:
  33.   GMSLabel.pas : This component
  34.   LblEdit.pas  : Component editor for GMSLabel
  35.   GMSLabel.dcr : In the 16 directory for Delphi 1
  36.   GMSLabel.dcr : In the 32 directory for Delphi 2 & 3
  37.  
  38. Installation:
  39.   Copy the above pas files and the *.dcr file in the (16 Dir Delphi1)
  40.   or (32 Dir Delphi 2 & 3) into one of the dirs in your component lib
  41.   search path.  Then install gmslabel.pas & lbledit.pas.
  42.   Only GMSStickyLabel will appear on your component pallet under GMS.
  43.  
  44. Copyright:
  45.   This component is free if you keep this comment header.
  46.   Any damage real or imagined caused by this component is
  47.   100% your responsibility not GMS Computing Inc.'s.
  48.  
  49. Thank You
  50.   This free component is my way of saying thank you to The Delphi Community.
  51.   People have been more than helpful to me in the forums & newsgroups,
  52.   especially team B members, Wayne Niddery, and Jacques Scoatarin.
  53.   As an example of how great a community we have within a day of sending
  54.   this component out Jacques Scoatarin basically added the lower level api
  55.   calls to enable features 7 & 8 which make the component much more robust.
  56.   Enjoy!
  57.  
  58.   If you like and use this component e-mail to let me know.
  59.   P.S. GMS Computing Inc.(which is me) is always looking for new contracts.
  60.   If you like what you see then contact me.  See my web page for more details.
  61.  
  62. VERSION INFO
  63. GMSStickyLabel v1.1 July/5/97  by Glenn Shukster & Jacques Scoatarin
  64.     - Released on public.
  65.  V 1.2  Aug/14/97
  66.     - Thanks to Erik B. Berry <berry@elvis.rhodes.edu> &
  67.       Jean-Christophe Boggio <cat@gestalt.freenix.fr> who reported the
  68.       behavior below
  69.     - Corrected weird behavior that occured when the panel was aligned
  70.       bottom and then you assign the TGMSStickylabel
  71.     - Corrected if TGMSStickyLabel is moved from _AttachedTo component
  72.       back to the same _AttachedTo component it would not realign itself.
  73.       Now it does.
  74.     - Corrected when selecting _AttachedTo you could select a component
  75.       who did not have the same parent with poor results:  Added a
  76.       property editor that only displays TWinControls that have the same parent.
  77.  V 1.3 Sep/22/97
  78.     - Thanks to Gerald  gerald@hydra.hkstar.com for reporting the following bug
  79.     - Bug in only Delphi3 version.  When there is something aligned to top and
  80.       a new TGMSStickyLabel is dropped on a component it will loop through all the
  81.       components 3 times with the RectBounds of the TGMSStickyLabel being incorrect
  82.       until the last loop.   In Delphi2 & 1 it only goes thought the loop once with
  83.       the correct co-ordinates.
  84.       Solution was that only attach if (Self.BoundsRect.Top > 0)
  85.       This is a trade off for if you ever try to drop a component at position 0 it will
  86.       not attach.  Drop it just a bit below 0 and it will align no problem.
  87.     - Thanks to Erik B. Berry <berry@elvis.rhodes.edu> for the below improvement
  88.       Eric suggested to have the component alignment be laRightJustify if the _AlignTo
  89.       is alLeft.  This way when editing the caption it will grow away from the control
  90.       its attached to, thus not asking to attach to it again.
  91.  V 1.4 Nov/12/97
  92.     - Added options the following options to the property editor
  93.       alignment (right, left, top, bottom), Set gap, Edit Caption
  94. }
  95.  
  96. unit GMSLabel;
  97.  
  98. {$D-} { Turns debugger off  comment this line out if you want to step through it}
  99.  
  100. interface
  101.  
  102. uses
  103.   Classes,
  104.   StdCtrls,
  105.   Controls,
  106.   Messages,
  107.   Forms,
  108.   Dialogs,
  109.   DsgnIntf,
  110. {$IFDEF WIN32}
  111.   SysUtils, { for writing to file for debugging purposes}
  112.   Windows
  113. {$ELSE}
  114.   WinProcs, WinTypes
  115. {$ENDIF}
  116. ;
  117.  
  118. type
  119.   TAlignTo = (alLeft, alTop, alBottom,  alRight);
  120.   TGMSStickyLabel = class(TLabel)
  121.   private
  122.     FAttachTo: TWinControl;
  123.     FAlignTo: TAlignTo;
  124.     FGap : Integer;
  125.     FDefAttachedProc: Pointer;
  126.     FAttachedInstance: Pointer;
  127.     FRealigning: Boolean;
  128.     Procedure SetGap(Value: Integer);
  129.     procedure SetAttachTo(Value: TWinControl);
  130.     Procedure SetAlignTo(Value: TAlignTo);
  131.     { New Attached controls WndProc }
  132.     procedure AttachedWndProc(var Message: TMessage);
  133.     { Procedure ErrFile(sString: String);}
  134.   protected
  135.     procedure CheckForControl;
  136.     procedure Notification(AComponent: TComponent; Operation: TOperation); override;
  137.     procedure SetParent(AParent: TWinControl); override;
  138.     { Override WndProc }
  139.     procedure WndProc(var Message: TMessage); override;
  140.   public
  141.     Procedure _ReAlign;
  142.     constructor Create(AOwner: TComponent); override;
  143.     destructor Destroy; override;
  144.   published
  145.     property _AlignTo: TAlignTo read FAlignTo write SetAlignTo default alLeft;
  146.     property _AttachTo: TWinControl read FAttachTo write SetAttachTo;
  147.     Property _Gap : Integer Read FGap write SetGap Default 5;
  148.   end;
  149.  
  150. procedure Register;
  151.  
  152. implementation
  153.  
  154. constructor TGMSStickyLabel.Create(AOwner: TComponent);
  155. begin
  156.   inherited Create(AOwner);
  157.   FGap := 5;
  158.   FRealigning := False;
  159.   { Make Instance out of method }
  160.   FAttachedInstance := MakeObjectInstance(AttachedWndProc);
  161. end;
  162.  
  163. destructor TGMSStickyLabel.Destroy;
  164. begin
  165.   { Restore original Attach Control WndProc }
  166.   {   IsWindow check may be uneccessary but doesn't hurt ti be 100% sure }
  167.   if Assigned(FAttachTo) and IsWindow(FAttachTo.Handle) then
  168.     SetWindowLong(FAttachTo.Handle, GWL_WNDPROC, Longint(FDefAttachedProc));
  169.   { Make method Instance }
  170.   FreeObjectInstance(FAttachedInstance);
  171.   inherited Destroy;
  172. end;
  173.  
  174. procedure TGMSStickyLabel.AttachedWndProc(var Message: TMessage);
  175. begin
  176.   with Message do
  177.   begin
  178.     case Msg of
  179.       { On Move/Size message call _ReAlign to keep us aligned! }
  180.       WM_MOVE, WM_SIZE : _ReAlign;
  181.     end;
  182.     Result := CallWindowProc(FDefAttachedProc, FAttachTo.Handle, Msg, WParam, LParam);
  183.   end;
  184. end;
  185.  
  186. procedure TGMSStickyLabel.CheckForControl;
  187. var
  188.   I: Integer;
  189.   RCDest: TRect;
  190. begin
  191.   { if - for not checking if already attached ? }
  192.   { if not Assigned(FAttachTo) then }
  193.   with Owner do
  194.   begin
  195.     for I := 1 to ComponentCount do
  196.     if (Components[I - 1] is TWinControl) and (Components[I - 1] <> Self) then
  197.     with Components[I - 1] as TWinControl do
  198.     if (Parent = Self.Parent) then
  199.     begin
  200.       {
  201.       ErrFile('Name:'+Name +'  Parent:'+ Parent.Name+ ' Self:'+Self.Name+#13 +
  202.                  'Self.BoundsRect.Top   '+IntToStr(Self.BoundsRect.Top)+ #13 +
  203.                  'Self.BoundsRect.Left   '+IntToStr(Self.BoundsRect.Left)+ #13 +
  204.                  'Self.BoundsRect.Bottom'+IntToStr(Self.BoundsRect.Bottom)+ #13 +
  205.                  'BoundsRect.Top'+IntToStr(BoundsRect.Top) + #13 +
  206.                  'BoundsRect.Left'+IntToStr(BoundsRect.Left) + #13 +
  207.                  'BoundsRect.Bottom'+IntToStr(BoundsRect.Bottom)
  208.                  );
  209.                  }
  210.       If (Self.BoundsRect.Top > 0) Then
  211.         begin
  212.           IntersectRect(RCDest, Self.BoundsRect, BoundsRect);
  213.           if not IsRectEmpty(RCDest) then
  214.           begin
  215.             {ErrFile('Asked to attach to '+Name+#13+#13);}
  216.             if MessageDlg('Attach label to ' + Name, mtConfirmation, [mbYes, mbNo], 0) = mrYes then
  217.             begin
  218.               _AttachTo := Owner.Components[I - 1] as TWinControl;
  219.               FocusControl := Owner.Components[I - 1] as TWinControl;
  220.             end;
  221.             break;
  222.           end;
  223.         end;
  224.     end;
  225.   end;
  226. end;
  227.  
  228. procedure TGMSStickyLabel.SetParent(AParent: TWinControl);
  229. var
  230.   FOrigParent: TWinControl;
  231. begin
  232.   FOrigParent := Parent;
  233.   inherited SetParent(AParent);
  234.   if (Parent <> Nil) and not Assigned(FOrigParent) then
  235.     CheckForControl;
  236. end;
  237.  
  238. procedure TGMSStickyLabel.Notification(AComponent: TComponent; Operation: TOperation);
  239. begin
  240.   { dont forget to check if indeed it is FAttachTo that is being removed }
  241.   if (Operation = opRemove) and (AComponent = FAttachTo) then
  242.     FAttachTo := Nil;
  243.   inherited Notification(AComponent,Operation);
  244. end;
  245.  
  246. procedure TGMSStickyLabel.WndProc(var Message: TMessage);
  247. begin
  248.   with Message do
  249.   begin
  250.     case Msg of
  251.       { On change of position check for controls to attach to }
  252.       WM_WINDOWPOSCHANGED:
  253.         if (not FRealigning) and (csDesigning in ComponentState) then
  254.           CheckForControl;
  255.     end;
  256.   end;
  257.   inherited WndProc(Message);
  258. end;
  259.  
  260. procedure TGMSStickyLabel.SetAttachTo(Value: TWinControl);
  261. begin
  262.   if (FAttachTo <> Value) then
  263.   begin
  264.     { Restore original previously Attach Control WndProc }
  265.     {   IsWindow check may be uneccessary but doesn't hurt to be 100% sure }
  266.     If (Assigned(FAttachTo)= False) or (Assigned(FAttachTo) and (Value.Parent = Self.Parent)) Then {gms}
  267.       begin
  268.         if Assigned(FAttachTo) and IsWindow(FAttachTo.Handle) then
  269.            SetWindowLong(FAttachTo.Handle, GWL_WNDPROC, Longint(FDefAttachedProc));
  270.         FAttachTo := Value;
  271.         if Assigned(FAttachTo) and IsWindow(FAttachTo.Handle) then
  272.         begin
  273.           { Get original Attach Control WndProc }
  274.           FDefAttachedProc := Pointer(GetWindowLong(FAttachTo.Handle, GWL_WNDPROC));
  275.           { Set the new Attach Control WndProc - our own method! }
  276.           SetWindowLong(FAttachTo.Handle, GWL_WNDPROC, Longint(FAttachedInstance));
  277.           _ReAlign;
  278.         end;
  279.       end
  280.     else
  281.       if (Assigned(FAttachTo) and (Value.Parent <> Self.Parent)) Then
  282.          ShowMessage('Must have the same parents '+ #13#10 +
  283.                      'AttachTo Parent is '+ TControl(Value.Parent).Name + #13#10 +
  284.                      'TGMSStickyLabel Parent is '+ TControl(Self.Parent).Name);
  285.   end
  286.  else
  287.    _ReAlign; { GMS if assigned back to the same component it will realign itself}
  288. end;
  289.  
  290. Procedure TGMSStickyLabel.SetAlignTo(Value: TAlignTo);
  291. begin
  292.  If (FAlignTo <> Value) then
  293.     begin
  294.       FAlignTo := Value;
  295.       _ReAlign;
  296.     end ;
  297. end;
  298.  
  299. Procedure TGMSStickyLabel.SetGap(Value: Integer);
  300. begin
  301.   If (FGap <> Value) Then
  302.     begin
  303.       FGap := Value;
  304.       _ReAlign;
  305.     end;
  306. end;
  307.  
  308. Procedure TGMSStickyLabel._ReAlign;
  309. var
  310.   iNewTop, iNewLeft: Integer;
  311. begin
  312.   iNewTop := 0;  { to get rid of warnings}
  313.   iNewLeft := 0; { to get rid of warnings}
  314.   FRealigning := True;
  315.   If FAttachTo <> Nil then
  316.   begin
  317.     Case FAlignTo of
  318.        alLeft:
  319.          begin
  320.           iNewTop :=  FAttachTo.Top;
  321.           iNewLeft := FAttachTo.Left - Width - FGap ;
  322.           Alignment := taRightJustify;
  323.          end ;
  324.        alRight:
  325.          begin
  326.           iNewTop := FAttachTo.Top;
  327.           iNewLeft := FAttachTo.Left + FAttachTo.Width + FGap ;
  328.           Alignment := taLeftJustify;
  329.          end ;
  330.        alTop:
  331.          begin
  332.           iNewTop := FAttachTo.Top - Height - FGap ;
  333.           iNewLeft := FAttachTo.Left ;
  334.           Alignment := taLeftJustify;
  335.          end;
  336.        alBottom:
  337.          begin
  338.           iNewTop := FAttachTo.Top + FAttachTo.Height + FGap ;
  339.           iNewLeft := FAttachTo.Left ;
  340.           Alignment := taLeftJustify;
  341.          end;
  342.     end;
  343.     { Set all propertied in one call to avoid multiple re-drawing & pos changes }
  344.     SetBounds(iNewLeft, iNewTop, Width, Height);
  345.   end;
  346.   FRealigning := False;
  347. end;
  348.  
  349. (*
  350. Procedure TGMSStickyLabel.ErrFile(sString: String);
  351. const
  352.   cFileName = 'c:\Event.txt';
  353. var
  354.   FLog: TextFile;
  355. begin
  356.   AssignFile(FLog, cFileName);
  357.   if FILEEXISTS(cFileName) Then
  358.      Append(FLog)
  359.   else
  360.      ReWrite(FLog);
  361.   Writeln(FLog,sString);
  362.   CloseFile(FLog); {Close file, save changes}
  363. end;
  364.   *)
  365.  
  366.  
  367. {PROPERTY EDITOR}
  368. type
  369.     TAttachToEditor = class(TComponentProperty)
  370.     public
  371.       procedure GetValues(Proc: TGetStrProc); override;
  372.     end;
  373.  
  374. procedure TAttachToEditor.GetValues(Proc: TGetStrProc);
  375. var
  376.   II: Integer;
  377.   Values: TStringList;
  378.   oGMSStickyLabel : TGMSStickyLabel;
  379.   P,P1 : TWinControl;
  380. begin
  381.   Values := TStringList.Create;
  382.   try
  383.     oGMSStickyLabel := GetComponent(0) as TGMSStickyLabel;
  384.     P := oGMSStickyLabel.Parent;
  385.     for II := 0 to P.ControlCount-1 do begin
  386.       P1 := TWinControl(P.Controls[II]);
  387.       if (P1 is TWinControl)
  388.         and ((P.Controls[ii] is TGMSStickyLabel) = False)
  389.         and (P1.Name <> '') then
  390.           Values.Add(P1.Name);
  391.     end;
  392.     for II := 0 to Values.Count - 1 do Proc(Values[II]);
  393.   finally
  394.     Values.Free;
  395.   end;
  396. end;
  397.  
  398. procedure Register;
  399. begin
  400.   RegisterComponents('GMS', [TGMSStickyLabel]);
  401.   RegisterPropertyEditor(TypeInfo(TWinControl),TGMSStickyLabel,'_AttachTo',TAttachToEditor);
  402. end;
  403.  
  404. end.
  405.